<?php

mysqli_report(MYSQLI_REPORT_ERROR);

class Kd_Db_Driver_Mysqli extends Kd_Db_Driver_Base {

    private $_link = NULL;
    private $_isTransaction = FALSE;

    public function __construct() {
        parent::__construct();
    }

    public function isConnected() {
        return $this->_link ? TRUE : FALSE;
    }

    public function isTransaction() {
        return $this->_isTransaction;
    }

    public function escapeString($value) {
        return $this->_link->escape_string($value);
    }

    public function setSql($sql, $params = array()) {
        $this->originSql = $sql;
        $this->boundSql = str_replace('{t}', Kd_Db_Config::getTablePrefix(), $this->originSql);
        if (is_array($params)) {
            preg_match_all('/(:\w+)(:[is])?/', $this->boundSql, $matches);
            $paramNames = $matches[1];
            $paramTypes = $matches[2];
            for ($i = 0; $i < count($paramNames); $i++) {
                $n = substr($paramNames[$i], 1);
                $t = empty($paramTypes[$i]) ? 's' : substr($paramTypes[$i], 1);
                $v = $params[$n];
                if (is_array($v)) {
                    $nv = array();
                    foreach ($v as $sv) {
                        $nv[] = $t == 's' ? "'" . $this->escapeString($sv) . "'" : $this->escapeString($sv);
                    }
                    $v = implode(',', $nv);
                } else {
                    if (is_null($v)) {
                        $v = 'NULL';
                    } else {
                        $v = $t == 's' ? "'" . $this->escapeString($v) . "'" : $this->escapeString($v);
                    }
                }
                $this->boundSql = str_replace($matches[0][$i], $v, $this->boundSql);
            }
        }
        return $this;
    }

    public function connect() {
        if (!$this->_link) {
            $this->_link = new Mysqli($this->getServer(), $this->getUsername(), $this->getPassword(), $this->getDatabase());
            if ($this->_link->connect_errno) {
                throw new Kd_Db_Exception($this->_link->connect_errno . ';' . $this->_link->connect_error);
            }
        }
        return $this;
    }

    public function disconnect() {
        if ($this->_link) {
            $this->_link->close();
            $this->_link = NULL;
        }
    }

    public function getInsertId() {
        return $this->_link->insert_id;
    }

    public function beginTransaction() {
        if ($this->_isTransaction === FALSE) {
//            $this->_link->autocommit(FALSE);
            $this->_isTransaction = TRUE;
        }
        return $this;
    }

    public function commitTransaction() {
        if ($this->_isTransaction) {
//            $this->_link->commit();
            $this->_isTransaction = FALSE;
        }
        return $this;
    }

    public function rollbackTransaction() {
        if ($this->_isTransaction) {
//            $this->_link->rollback();
            $this->_isTransaction = FALSE;
        }
        return $this;
    }

    public function execute() {
        $this->_link->query("SET NAMES 'utf8'");
        return $this->_link->query($this->boundSql);
    }

    public function getAffectedRows() {
        return $this->_link->affected_rows;
    }

    public function fetch() {
        $iter = $this->execute();
        $result = new Kd_Db_Result();
        while ($row = $iter->fetch_assoc()) {
            $result->append($row);
        }
        $iter->close();
        return $result;
    }

    public function fetchLimit($limit, $offset) {
        if (!empty($limit) && $limit > 0) {
            $this->boundSql .= "\nLIMIT $offset,$limit";
        }
        return $this->fetch();
    }

}